package ch.ti.bfh.app.loodel.internal.mail;

import ch.ti.bfh.app.loodel.domain.invitation.GuestLearningEventInvitation;
import ch.ti.bfh.app.loodel.domain.invitation.LearningEventInvitation;
import ch.ti.bfh.app.loodel.domain.invitation.LearningEventInvitationRepository;
import ch.ti.bfh.app.loodel.domain.invitation.MemberLearningEventInvitation;
import ch.ti.bfh.app.loodel.domain.learningEvent.LearningEvent;
import ch.ti.bfh.app.loodel.domain.learningEvent.LearningEventRepository;
import ch.ti.bfh.app.loodel.domain.member.Member;
import ch.ti.bfh.app.loodel.domain.member.MemberRepository;
import ch.ti.bfh.app.loodel.domain.timeslot.TimeSlot;
import ch.ti.bfh.app.loodel.internal.security.InternalUserContext;
import ch.ti.bfh.app.loodel.service.LearningEventInvitationData;
import ch.ti.bfh.app.loodel.service.MemberData;
import ch.ti.bfh.app.loodel.service.SendLearningEventInvitationService;
import ch.ti.bfh.app.loodel.service.create.CreateLearningEventData;
import ch.ti.bfh.app.loodel.service.create.TimeSlotVoteSearchService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.Validate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

@Service
@Transactional
public class DefaultSendLearningEventInvitationService implements SendLearningEventInvitationService {

    private final MemberRepository memberRepository;

    private final LoodelMailService loodelMailService;

    private final InternalUserContext userContext;

    private final LearningEventRepository learningEventRepository;

    private final LearningEventInvitationRepository learningEventInvitationRepository;

    private final TimeSlotVoteSearchService timeSlotVoteSearchService;

    @Inject
    public DefaultSendLearningEventInvitationService(MemberRepository memberRepository, LoodelMailService loodelMailService, InternalUserContext userContext, LearningEventRepository learningEventRepository, LearningEventInvitationRepository learningEventInvitationRepository, TimeSlotVoteSearchService timeSlotVoteSearchService) {
        this.memberRepository = memberRepository;
        this.loodelMailService = loodelMailService;
        this.userContext = userContext;
        this.learningEventRepository = learningEventRepository;
        this.learningEventInvitationRepository = learningEventInvitationRepository;
        this.timeSlotVoteSearchService = timeSlotVoteSearchService;
    }


    @Override
    public MemberData getMemberDataForInvitation(String email) {
        Member member = memberRepository.findByEmail(email);
        if (member != null) {
            return new MemberData(member.getEmail(), member.getFullName());
        }
        return new MemberData(email, "GUEST MEMBER");
    }

    @Override
    public List<MemberData> findMemberDataForInvitation(String queryTerm) {
        List<MemberData> memberDatas = timeSlotVoteSearchService.findMembersWithSameTimeSlotVotesAsCurrentMember(queryTerm);
        memberDatas.add(0, new MemberData(queryTerm, "Guest Member"));
        return memberDatas;
    }

    @Override
    public List<MemberData> findMemberDataForInvitationOfExistingLearningEvent(String queryTerm, Long learningEventId) {
        List<MemberData> memberDataForInvitation = this.findMemberDataForInvitation(queryTerm);
        List<Member> invitedMembers = learningEventInvitationRepository.findInvitedMembers(learningEventId);
        Iterator<MemberData> iterator = memberDataForInvitation.iterator();
        while (iterator.hasNext()) {
            MemberData next = iterator.next();
            for (Member invitedMember : invitedMembers) {
                if (next.geteMail().equals(invitedMember.getEmail())) {
                    iterator.remove();
                    break;
                }
            }
        }
        return memberDataForInvitation;
    }

    @Override
    public void sendLearningEventUpdateNofificationMail(String learningEventId, LearningEventInvitationData learningEventInvitationData) {
        Validate.notNull(learningEventInvitationData);
        Validate.notNull(learningEventInvitationData.getEmailList());
        LearningEvent learningEvent = learningEventRepository.getOne(learningEventId);
        for (String eMail : learningEventInvitationData.getEmailList()) {
            this.loodelMailService.sendLearningEventUpdateNofificationMail(learningEvent, eMail);
        }
    }


    @Override
    public void sendLearningEventInvitation(String learningEventId, LearningEventInvitationData learningEventInvitationData) {
        Validate.notNull(learningEventInvitationData);
        Validate.notNull(learningEventInvitationData.getEmailList());
        LearningEvent learningEvent = learningEventRepository.getOne(learningEventId);
        Member currentUser = userContext.getCurrentMember();
        List<LearningEventInvitation> learningEventInvitationList = new ArrayList<LearningEventInvitation>();
        if (CollectionUtils.isNotEmpty(learningEventInvitationData.getEmailList())) {
            for (String mail : learningEventInvitationData.getEmailList()) {
                Member recipientMember = memberRepository.findByEmail(mail);
                if (recipientMember == null) {
                    learningEventInvitationList.add(new GuestLearningEventInvitation(learningEvent, currentUser, mail));
                } else {
                    learningEventInvitationList.add(new MemberLearningEventInvitation(learningEvent, currentUser, recipientMember));
                }
            }
        }

        learningEventInvitationRepository.save(learningEventInvitationList);

        //send mail
        for (LearningEventInvitation learningEventInvitation : learningEventInvitationList) {
            loodelMailService.sendLearningEventInvitationMail(learningEventInvitation, learningEventInvitationData.getCustomText());
        }
    }

    @Override
    public String getInvitationDefaultText(CreateLearningEventData createLearningEventData, String customText) {
        Member currentUser = userContext.getCurrentMember();
        HashSet<TimeSlot> timeSlots = new HashSet<TimeSlot>();
        LearningEvent learningEvent = new LearningEvent(currentUser, createLearningEventData.getGroupName(), createLearningEventData.getModuleName(), timeSlots);
        learningEvent.setDescription(createLearningEventData.getComment());
        //timeSlots.add(new TimeSlot(learningEvent, new Interval(new DateTime(), new DateTime()), new Location("", "", "")));
        GuestLearningEventInvitation eventInvitation = new GuestLearningEventInvitation(learningEvent, currentUser, "Max.Tester@max.com");
        return loodelMailService.getLearningEventInvitationText(eventInvitation, customText);
    }
}
